﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System.Windows.Forms
{
    /// <summary>
    /// 表示可选中按钮
    /// </summary>
    /// <creator>marc</creator>
    public class SelectableButton : Button
    {
        private Color _borderColor = Color.FromArgb(255, 79, 129, 189);
        private bool _isMouseHover = false;
        private bool _isMouseDown = false;
        private bool _isSelected = false;
        private string _selectedText = string.Empty;

        /// <summary>
        /// 启用选中功能,默认true
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [DefaultValue(true)]
        [Description("启用选中功能,默认true")]
        public bool EnableSelected { get; set; } = true;

        /// <summary>
        /// 是否自动选中,默认true
        /// <para>true:则点击事件自动切换选中状态,false:则需要在代码中通过<see cref="IsSelected"/>改变选中状态</para>
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [DefaultValue(true)]
        [Description("是否自动选中,默认true")]
        public bool AutoSelected { get; set; } = true;

        /// <summary>
        /// 是否选中
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [DefaultValue(false)]
        [Description("是否选中")]
        public bool IsSelected
        {
            get => _isSelected;
            set
            {
                if (!EnableSelected)
                {
                    return;
                }

                if (value)
                {
                    Selected(true);
                }
                else
                {
                    UnSelected(true);
                }
            }
        }

        /// <summary>
        /// 选中的文字
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [DefaultValue("")]
        [Description("选中的文字")]
        public string SelectedText
        {
            get
            {
                if (string.IsNullOrEmpty(_selectedText))
                {
                    return Text;
                }
                return _selectedText;
            }
            set
            {
                _selectedText = value;
            }
        }

        /// <summary>
        /// 选中时的前景颜色
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [Description("选中时的前景颜色")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public Color SelectedForeColor { get; set; } = DefaultForeColor;

        /// <summary>
        /// 选中时的背景颜色
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [Description("选中时的背景颜色")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public Color SelectedBackColor { get; set; } = DefaultBackColor;

        /// <summary>
        /// 所属分组
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [DefaultValue("")]
        [Description("所属分组")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public string Group { get; set; } = string.Empty;

        /// <inheritdoc/>
        protected override void OnPaint(PaintEventArgs pevent)
        {
            Color foreColor = IsSelected ? SelectedForeColor : ForeColor;
            Color backColor = IsSelected ? SelectedBackColor : BackColor;

            string text = IsSelected ? SelectedText : Text;

            using (Brush brush = new SolidBrush(backColor))
            {
                pevent.Graphics.FillRectangle(brush, ClientRectangle);
            }

            float borderWidth = 2.2f;
            using (Pen pen = new Pen(_borderColor, borderWidth))
            {
                pevent.Graphics.DrawRectangle(pen, new Rectangle(0, 0, Width - 1, Height - 1));
            }
            RectangleF rectangle = new RectangleF(borderWidth, borderWidth, Width - 1 - borderWidth * 2, Height - 1 - borderWidth * 2);
            if (_isMouseHover && !_isMouseDown)
            {
                using (Brush brush = new SolidBrush(Color.FromArgb(120, Color.White)))
                {
                    pevent.Graphics.FillRectangle(brush, rectangle);
                }
            }
            if (_isMouseDown)
            {
                using (Brush brush = new SolidBrush(Color.FromArgb(20, Color.Black)))
                {
                    pevent.Graphics.FillRectangle(brush, rectangle);
                }
            }
            using (Brush brush = new SolidBrush(foreColor))
            {
                StringFormat stringFormat = new StringFormat
                {
                    Alignment = StringAlignment.Center,
                    LineAlignment = StringAlignment.Center
                };
                pevent.Graphics.DrawString(text, Font, brush, rectangle, stringFormat);
            }
        }
        /// <inheritdoc/>
        protected override void OnMouseEnter(EventArgs eventargs)
        {
            base.OnMouseEnter(eventargs);
            _isMouseHover = true;
        }
        /// <inheritdoc/>
        protected override void OnMouseHover(EventArgs e)
        {
            base.OnMouseHover(e);
            _isMouseHover = true;
        }
        /// <inheritdoc/>
        protected override void OnMouseLeave(EventArgs eventargs)
        {
            base.OnMouseLeave(eventargs);
            _isMouseHover = false;
        }
        /// <inheritdoc/>
        protected override void OnMouseDown(MouseEventArgs mevent)
        {
            //Debug.WriteLine(nameof(OnMouseDown));
            base.OnMouseDown(mevent);
            _isMouseDown = true;
            Invalidate();
        }
        /// <inheritdoc/>
        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            //Debug.WriteLine(nameof(OnMouseUp));
            base.OnMouseUp(mevent);
            _isMouseDown = false;
            Invalidate();
        }
        /// <inheritdoc/>
        protected override void OnMouseClick(MouseEventArgs e)
        {
            //Debug.WriteLine(nameof(OnMouseClick));
            base.OnMouseClick(e);
            if (AutoSelected)
            {
                IsSelected = !IsSelected;
            }
        }

        private List<SelectableButton> GetGroupMembers()
        {
            List<SelectableButton> selectableButtons = new List<SelectableButton>();
            if (string.IsNullOrWhiteSpace(Group))
            {
                return selectableButtons;
            }

            if (Parent != null)
            {
                List<SelectableButton> buttons = null;
                if (buttons == null)
                {
                    Control root = null;
                    Control parent = Parent;
                    while (parent != null)
                    {
                        root = parent;
                        parent = parent.Parent;
                    }

                    buttons = FindSelectableButton(root);
                }
                foreach (var control in buttons)
                {
                    SelectableButton selectableButton = control as SelectableButton;
                    if (selectableButton != null && selectableButton != this && selectableButton.Group.Equals(Group))
                    {
                        selectableButtons.Add(selectableButton);
                    }
                }
            }
            return selectableButtons;
        }

        private List<SelectableButton> FindSelectableButton(Control parent)
        {
            List<SelectableButton> buttons = new List<SelectableButton>();

            ControlCollection controls = parent.Controls;
            if (controls.Count == 0)
            {
                return buttons;
            }
            foreach (Control control in controls)
            {
                if (control is SelectableButton button)
                {
                    buttons.Add(button);
                }
                else
                {
                    buttons.AddRange(FindSelectableButton(control));
                }
            }

            return buttons;
        }
        private void Selected(bool checkGroup)
        {
            if (checkGroup)
            {
                GetGroupMembers().ForEach(selectableButton =>
                {
                    if (selectableButton != this)
                    {
                        selectableButton.UnSelected(false);
                    }
                });
            }
            _isSelected = true;
            Invalidate();
        }
        private void UnSelected(bool checkGroup)
        {
            if (checkGroup)
            {
                bool hasGroupMember = GetGroupMembers().Count > 0;
                if (!hasGroupMember)
                {
                    _isSelected = false;
                }
            }
            else
            {
                _isSelected = false;
            }
            Invalidate();
        }

        ///// <summary>
        ///// 触发点击事件 
        ///// </summary>
        //public void PerformClick()
        //{
        //    MouseEventArgs mevent = new MouseEventArgs(MouseButtons.Left, 1, 3, 3, 0);

        //    OnMouseClick(mevent);
        //}
    }
}
